/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
 
This file is part of Quake III Arena source code.
 
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
 
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
===========================================================================
*/


#ifndef TR_LOCAL_H
#define TR_LOCAL_H

#include "../game/q_shared.h"
#include "qfiles.h"
#include "qcommon.h"
#include "tr_public.h"
#include "qgl.h"

#define GL_INDEX_TYPE		GL_UNSIGNED_INT
typedef unsigned int glIndex_t;

// everything that is needed by the backend needs
// to be double buffered to allow it to run in
// parallel on a dual cpu machine
#define	SMP_FRAMES		2

// 12 bits
// see QSORT_SHADERNUM_SHIFT
#define	MAX_SHADERS				16384

//#define MAX_SHADER_STATES 2048
#define MAX_STATES_PER_SHADER 32
#define MAX_STATE_NAME 32

// can't be increased without changing bit packing for drawsurfs


typedef struct dlight_s
{
    vec3_t	origin;
    vec3_t	color;				// range from 0.0 to 1.0, should be color normalized
    float	radius;

    vec3_t	transformed;		// origin in local coordinate system
    int		additive;			// texture detail is lost tho when the lightmap is dark
}
dlight_t;


// a trRefEntity_t has all the information passed in by
// the client game, as well as some locally derived info
typedef struct
{
    refEntity_t	e;

    float		axisLength;		// compensate for non-normalized axis

    qboolean	needDlights;	// true for bmodels that touch a dlight
    qboolean	lightingCalculated;
    vec3_t		lightDir;		// normalized direction towards light
    vec3_t		ambientLight;	// color normalized to 0-255
    float		ambientLightInt[4];	// 32 bit rgba packed
    vec3_t		directedLight;
}
trRefEntity_t;


typedef struct
{
    vec3_t		origin;			// in world coordinates
    vec3_t		axis[3];		// orientation in world
    vec3_t		viewOrigin;		// viewParms->or.origin in local coordinates
    float		modelMatrix[16];
}
orientationr_t;

typedef struct image_s
{
    char		imgName[MAX_QPATH];		// game path, including extension
    int			width, height;				// source image
    int			uploadWidth, uploadHeight;	// after power of two and picmip but not including clamp to MAX_TEXTURE_SIZE
    GLuint		texnum;					// gl texture binding

    int			frameUsed;			// for texture usage in frame statistics

    int			internalFormat;
    int			target;
    int			TMU;				// only needed for voodoo2

    qboolean	mipmap;
    qboolean	allowPicmip;
    int			wrapClampMode;		// GL_CLAMP or GL_REPEAT

    struct image_s*	next;
}
image_t;

//===============================================================================

typedef enum {
    SS_BAD,
    SS_PORTAL,			// mirrors, portals, viewscreens
    SS_ENVIRONMENT,		// sky box
    SS_OPAQUE,			// opaque

    SS_DECAL,			// scorch marks, etc.
    SS_SEE_THROUGH,		// ladders, grates, grills that may have small blended edges
    // in addition to alpha test
    SS_BANNER,

    SS_FOG,

    SS_UNDERWATER,		// for items that should be drawn in front of the water plane

    SS_BLEND0,			// regular transparency and filters
    SS_BLEND1,			// generally only used for additive type effects
    SS_BLEND2,
    SS_BLEND3,

    SS_BLEND6,
    SS_STENCIL_SHADOW,
    SS_ALMOST_NEAREST,	// gun smoke puffs

    SS_NEAREST			// blood blobs
} shaderSort_t;


#define MAX_SHADER_STAGES 8

typedef enum {
    GF_NONE,

    GF_SIN,
    GF_SQUARE,
    GF_TRIANGLE,
    GF_SAWTOOTH,
    GF_INVERSE_SAWTOOTH,

    GF_NOISE

} genFunc_t;


typedef enum {
    DEFORM_NONE,
    DEFORM_WAVE,
    DEFORM_NORMALS,
    DEFORM_BULGE,
    DEFORM_MOVE,
    DEFORM_PROJECTION_SHADOW,
    DEFORM_AUTOSPRITE,
    DEFORM_AUTOSPRITE2,
    DEFORM_TEXT0,
    DEFORM_TEXT1,
    DEFORM_TEXT2,
    DEFORM_TEXT3,
    DEFORM_TEXT4,
    DEFORM_TEXT5,
    DEFORM_TEXT6,
    DEFORM_TEXT7
} deform_t;

typedef enum {
    AGEN_IDENTITY,
    AGEN_SKIP,
    AGEN_ENTITY,
    AGEN_ONE_MINUS_ENTITY,
    AGEN_VERTEX,
    AGEN_ONE_MINUS_VERTEX,
    AGEN_LIGHTING_SPECULAR,
    AGEN_WAVEFORM,
    AGEN_PORTAL,
    AGEN_CONST
} alphaGen_t;

typedef enum {
    CGEN_BAD,
    CGEN_IDENTITY_LIGHTING,	// tr.identityLight
    CGEN_IDENTITY,			// always (1,1,1,1)
    CGEN_ENTITY,			// grabbed from entity's modulate field
    CGEN_ONE_MINUS_ENTITY,	// grabbed from 1 - entity.modulate
    CGEN_EXACT_VERTEX,		// tess.vertexColors
    CGEN_VERTEX,			// tess.vertexColors * tr.identityLight
    CGEN_ONE_MINUS_VERTEX,
    CGEN_WAVEFORM,			// programmatically generated
    CGEN_LIGHTING_DIFFUSE,
    CGEN_FOG,				// standard fog
    CGEN_CONST				// fixed color
} colorGen_t;

typedef enum {
    TCGEN_BAD,
    TCGEN_IDENTITY,			// clear to 0,0
    TCGEN_LIGHTMAP,
    TCGEN_TEXTURE,
    TCGEN_ENVIRONMENT_MAPPED,
    TCGEN_FOG,
    TCGEN_VECTOR			// S and T from world coordinates
} texCoordGen_t;

typedef enum {
    ACFF_NONE,
    ACFF_MODULATE_RGB,
    ACFF_MODULATE_RGBA,
    ACFF_MODULATE_ALPHA
} acff_t;

typedef struct
{
    genFunc_t	func;

    float base;
    float amplitude;
    float phase;
    float frequency;
}
waveForm_t;

#define TR_MAX_TEXMODS 4

typedef enum
{
    TMOD_NONE,
    TMOD_TRANSFORM,
    TMOD_TURBULENT,
    TMOD_SCROLL,
    TMOD_SCALE,
    TMOD_STRETCH,
    TMOD_ROTATE,
    TMOD_ENTITY_TRANSLATE
}
texMod_t;

#define	MAX_SHADER_DEFORMS	3
typedef struct
{
    deform_t	deformation;			// vertex coordinate modification type

    vec3_t		moveVector;
    waveForm_t	deformationWave;
    float		deformationSpread;

    float		bulgeWidth;
    float		bulgeHeight;
    float		bulgeSpeed;
}
deformStage_t;

typedef struct
{
    texMod_t		type;

    // used for TMOD_TURBULENT and TMOD_STRETCH
    waveForm_t		wave;

    // used for TMOD_TRANSFORM
    float			matrix[2][2];		// s' = s * m[0][0] + t * m[1][0] + trans[0]
    float			translate[2];		// t' = s * m[0][1] + t * m[0][1] + trans[1]

    // used for TMOD_SCALE
    float			scale[2];			// s *= scale[0]
										// t *= scale[1]

    // used for TMOD_SCROLL
    float			scroll[2];			// s' = s + scroll[0] * time
										// t' = t + scroll[1] * time

    float			rotateSpeed;		// + = clockwise
										// - = counterclockwise
}
texModInfo_t;

#define	MAX_IMAGE_ANIMATIONS	8
#define NUM_TEXTURE_BUNDLES 2
typedef struct
{
    image_t			*image[MAX_IMAGE_ANIMATIONS];
    int				numImageAnimations;
    float			imageAnimationSpeed;

    texCoordGen_t	tcGen;
    vec3_t			tcGenVectors[2];

    int				numTexMods;
    texModInfo_t	*texMods;

    int				videoMapHandle;
    qboolean		isLightmap;
    qboolean		vertexLightmap;
    qboolean		isVideoMap;
}
textureBundle_t;

typedef struct
{
    qboolean		active;

    textureBundle_t	bundle[NUM_TEXTURE_BUNDLES];

    waveForm_t		rgbWave;
    colorGen_t		rgbGen;

    waveForm_t		alphaWave;
    alphaGen_t		alphaGen;

    float			constantColor[4];				// for CGEN_CONST and AGEN_CONST

    unsigned		stateBits;					// GLS_xxxx mask

    acff_t			adjustColorsForFog;

    qboolean		isDetail;

	int				multitextureEnv;		// 0, GL_MODULATE, GL_ADD
}
shaderStage_t;

struct shaderCommands_s;

#define LIGHTMAP_2D			-4		// shader is for 2D rendering
#define LIGHTMAP_BY_VERTEX	-3		// pre-lit triangle models
#define LIGHTMAP_WHITEIMAGE	-2
#define	LIGHTMAP_NONE		-1

typedef enum
{
    CT_FRONT_SIDED,
    CT_BACK_SIDED,
    CT_TWO_SIDED
}
cullType_t;

typedef enum
{
    FP_NONE,		// surface is translucent and will just be adjusted properly
    FP_EQUAL,		// surface is opaque but possibly alpha tested
    FP_LE			// surface is trnaslucent, but still needs a fog pass (fog surface)
}
fogPass_t;

typedef struct
{
    float		cloudHeight;
    image_t		*outerbox[6], *innerbox[6];
}
skyParms_t;

typedef struct
{
    vec3_t	color;
    float	depthForOpaque;
}
fogParms_t;

#define C_Identity_Lighting		0x000001
#define C_Lighting_Diffuse		0x000002
#define C_Exact_Vertex			0x000004
#define C_Const					0x000008
#define C_Vertex				0x000010
#define C_One_Minus_Vertex		0x000020
#define C_Fog					0x000040
#define C_WaveForm				0x000080
#define C_Entity				0x000100
#define C_One_Minus_Entity		0x000200

#define A_Const					0x000001
#define A_WaveForm				0x000002
#define A_Lighting_Specular		0x000004
#define A_Entity				0x000008
#define A_One_Minus_Entity		0x000010
#define A_Vertex				0x000020
#define A_One_Minus_Vertex		0x000040
#define A_Portal				0x000080

#define T_Texture				0x000001
#define T_LightMap				0x000002
#define T_Vector				0x000004
#define T_Fog					0x000008
#define T_Enviroment_Mapped		0x000010
#define TM_Scroll				0x000020
#define TM_Transform			0x000040
#define TM_Rotate				0x000080
#define TM_Turbulent			0x000100

#define M_CurrentEntTexCoord	0x000001
#define W_Sin					0x000002
#define W_Square				0x000004
#define W_SawTooth				0x000008
#define W_InverseSawTooth		0x000010
#define W_Noise					0x000020
#define M_ATEST_GT_0			0x000040
#define M_ATEST_LT_80			0x000080
#define M_ATEST_GE_80			0x000100

typedef struct
{
	int name[4];
	GLuint shader;
	int links;
} shaderFile_t;

typedef struct
{
	const char *vertexText;
	const char *fragmentText;
	const char *name;

	int		statebits;

	int		cfuncs;
	int		tfuncs;
	int		afuncs;
	int		mfuncs;

    GLuint program;
    shaderFile_t *vertex;
    shaderFile_t *fragment;

    int *samplers;
    int numSamplers;

	int *uniforms;
	int *uniformsValues;
	int numUniforms;
}
glShader_t;

typedef struct shader_s
{
    char		name[MAX_QPATH];		// game path, including extension
    int			lightmapIndex;			// for a shader to match, both name and lightmapIndex must match

    int			index;					// this shader == tr.shaders[index]
    int			sortedIndex;			// this shader == tr.sortedShaders[sortedIndex]

    float		sort;					// lower numbered shaders draw before higher numbered

    qboolean	defaultShader;			// we want to return index 0 if the shader failed to
    // load for some reason, but R_FindShader should
    // still keep a name allocated for it, so if
    // something calls RE_RegisterShader again with
    // the same name, we don't try looking for it again

    qboolean	explicitlyDefined;		// found in a .shader file

    int			surfaceFlags;			// if explicitlyDefined, this will have SURF_* flags
    int			contentFlags;

    qboolean	entityMergable;			// merge across entites optimizable (smoke, blood)

    qboolean	isSky;
    skyParms_t	sky;
    fogParms_t	fogParms;

    float		portalRange;			// distance to fog out at

    cullType_t	cullType;				// CT_FRONT_SIDED, CT_BACK_SIDED, or CT_TWO_SIDED
    qboolean	polygonOffset;			// set for decals and other items that must be offset
    qboolean	noMipMaps;				// for console fonts, 2D elements, etc.
    qboolean	noPicMip;				// for images that must always be full resolution

    fogPass_t	fogPass;				// draw a blended pass, possibly with depth test equals

    qboolean	needsNormal;			// not all shaders will need all data to be gathered
    qboolean	needsST1;
    qboolean	needsST2;
    qboolean	needsColor;

    int			numDeforms;
    deformStage_t	deforms[MAX_SHADER_DEFORMS];

    int			numUnfoggedPasses;
    shaderStage_t	*stages[MAX_SHADER_STAGES];

    void		(*optimalStageIteratorFunc)( void );

	glShader_t	*glShader;
	qboolean	glShaderFailed;

    float clampTime;                                  // time this shader is clamped to
    float timeOffset;                                 // current time offset for this shader

    int numStates;                                    // if non-zero this is a state shader
    struct shader_s *currentShader;                   // current state if this is a state shader
    struct shader_s *parentShader;                    // current state if this is a state shader
    int currentState;                                 // current state index for cycle purposes
    long expireTime;                                  // time in milliseconds this expires

    struct shader_s *remappedShader;                  // current shader this one is remapped too

    int shaderStates[MAX_STATES_PER_SHADER];          // index to valid shader states

    struct	shader_s	*next;
}
shader_t;

typedef struct shaderState_s
{
    char shaderName[MAX_QPATH];     // name of shader this state belongs to
    char name[MAX_STATE_NAME];      // name of this state
    char stateShader[MAX_QPATH];    // shader this name invokes
    int cycleTime;                  // time this cycle lasts, <= 0 is forever
    shader_t *shader;
}
shaderState_t;


// trRefdef_t holds everything that comes in refdef_t,
// as well as the locally generated scene information
typedef struct
{
    int			x, y, width, height;
    float		fov_x, fov_y;
    vec3_t		vieworg;
    vec3_t		viewaxis[3];		// transformation matrix

    int			time;				// time in milliseconds for shader effects and other time dependent rendering issues
    int			rdflags;			// RDF_NOWORLDMODEL, etc

    // 1 bits will prevent the associated area from rendering at all
    byte		areamask[MAX_MAP_AREA_BYTES];
    qboolean	areamaskModified;	// qtrue if areamask changed since last scene

    float		floatTime;			// tr.refdef.time / 1000.0

    // text messages for deform text shaders
    char		text[MAX_RENDER_STRINGS][MAX_RENDER_STRING_LENGTH];

    int			num_entities;
    trRefEntity_t	*entities;

    int			num_dlights;
    struct dlight_s	*dlights;

    int			numPolys;
    struct srfPoly_s	*polys;

    int			numDrawSurfs;
    struct drawSurf_s	*drawSurfs;


}
trRefdef_t;


//=================================================================================

// skins allow models to be retextured without modifying the model file
typedef struct
{
    char		name[MAX_QPATH];
    shader_t	*shader;
}
skinSurface_t;

typedef struct skin_s
{
    char		name[MAX_QPATH];		// game path, including extension
    int			numSurfaces;
    skinSurface_t	*surfaces[MD3_MAX_SURFACES];
}
skin_t;


typedef struct
{
    int			originalBrushNumber;
    vec3_t		bounds[2];

    float		color[4];
    float		tcScale;				// texture coordinate vector scales
    fogParms_t	parms;

    // for clipping distance in fog when outside
    qboolean	hasSurface;
    float		surface[4];
}
fog_t;

typedef struct
{
    orientationr_t	ori;
    orientationr_t	world;
    vec3_t		pvsOrigin;			// may be different than or.origin for portals
    qboolean	isPortal;			// true if this view is through a portal
    qboolean	isMirror;			// the portal is a mirror, invert the face culling
    int			frameSceneNum;		// copied from tr.frameSceneNum
    int			frameCount;			// copied from tr.frameCount
    cplane_t	portalPlane;		// clip anything behind this if mirroring
    int			viewportX, viewportY, viewportWidth, viewportHeight;
    float		fovX, fovY;
    float		projectionMatrix[16];
    cplane_t	frustum[4];
    vec3_t		visBounds[2];
    float		zFar;
}
viewParms_t;


/*
==============================================================================
 
SURFACES
 
==============================================================================
*/

// any changes in surfaceType must be mirrored in rb_surfaceTable[]
typedef enum {
    SF_BAD,
    SF_SKIP,				// ignore
    SF_FACE,
    SF_GRID,
    SF_TRIANGLES,
    SF_POLY,
    SF_MD3,
    SF_MD4,
    SF_FLARE,
    SF_ENTITY,				// beams, rails, lightning, etc that can be determined by entity
    SF_DISPLAY_LIST,

    SF_NUM_SURFACE_TYPES,
    SF_MAX = 0x7fffffff			// ensures that sizeof( surfaceType_t ) == sizeof( int )
} surfaceType_t;

typedef struct
{
    vec3_t		xyz;
    float		st[2];
    float		lightmap[2];
    vec3_t		normal;
    float		color[4];
}
drawVertex_t;

typedef struct drawSurf_s
{
    unsigned			sort;			// bit combination for fast compares
    surfaceType_t		*surface;		// any of surface*_t
}
drawSurf_t;

#define	MAX_FACE_POINTS		64

#define	MAX_PATCH_SIZE		32			// max dimensions of a patch mesh in map file
#define	MAX_GRID_SIZE		65			// max dimensions of a grid mesh in memory

// when cgame directly specifies a polygon, it becomes a srfPoly_t
// as soon as it is called
typedef struct srfPoly_s
{
    surfaceType_t	surfaceType;
    qhandle_t		hShader;
    int				fogIndex;
    int				numVerts;
    polyVert_t		*verts;
}
srfPoly_t;

typedef struct srfDisplayList_s
{
    surfaceType_t	surfaceType;
    int				listNum;
}
srfDisplayList_t;


typedef struct srfFlare_s
{
    surfaceType_t	surfaceType;
    vec3_t			origin;
    vec3_t			normal;
    vec3_t			color;
}
srfFlare_t;

typedef struct srfGridMesh_s
{
    surfaceType_t	surfaceType;

    // dynamic lighting information
    int				dlightBits[SMP_FRAMES];

    // culling information
    vec3_t			meshBounds[2];
    vec3_t			localOrigin;
    float			meshRadius;

    // lod information, which may be different
    // than the culling information to allow for
    // groups of curves that LOD as a unit
    vec3_t			lodOrigin;
    float			lodRadius;
    int				lodFixed;
    int				lodStitched;

    // vertexes
    int				width, height;
    float			*widthLodError;
    float			*heightLodError;
    drawVertex_t	verts[1];		// variable sized
}
srfGridMesh_t;

#ifdef COLOR_FLOAT
#define	VERTEXSIZE	11
#else
#define	VERTEXSIZE	8
#endif
typedef struct
{
    surfaceType_t	surfaceType;
    cplane_t	plane;

    // dynamic lighting information
    int			dlightBits[SMP_FRAMES];

    // triangle definitions (no normals at points)
    int			numPoints;
    int			numIndices;
    int			ofsIndices;
    float		points[1][VERTEXSIZE];	// variable sized
    // there is a variable length list of indices here also
}
srfSurfaceFace_t;


// misc_models in maps are turned into direct geometry by q3map
typedef struct
{
    surfaceType_t	surfaceType;

    // dynamic lighting information
    int				dlightBits[SMP_FRAMES];

    // culling information (FIXME: use this!)
    vec3_t			bounds[2];
    vec3_t			localOrigin;
    float			radius;

    // triangle definitions
    int				numIndexes;
    int				*indexes;

    int				numVerts;
    drawVertex_t	*verts;
}
srfTriangles_t;


extern	void (*rb_surfaceTable[SF_NUM_SURFACE_TYPES])(void *);

/*
==============================================================================
 
BRUSH MODELS
 
==============================================================================
*/


//
// in memory representation
//

#define	SIDE_FRONT	0
#define	SIDE_BACK	1
#define	SIDE_ON		2

typedef struct msurface_s
{
    int					viewCount;		// if == tr.viewCount, already added
    struct shader_s		*shader;
    int					fogIndex;

    surfaceType_t		*data;			// any of srf*_t
}
msurface_t;



#define	CONTENTS_NODE		-1
typedef struct mnode_s
{
    // common with leaf and node
    int			contents;		// -1 for nodes, to differentiate from leafs
    int			visframe;		// node needs to be traversed if current
    vec3_t		mins, maxs;		// for bounding box culling
    struct mnode_s	*parent;

    // node specific
    cplane_t	*plane;
    struct mnode_s	*children[2];

    // leaf specific
    int			cluster;
    int			area;

    msurface_t	**firstmarksurface;
    int			nummarksurfaces;
}
mnode_t;

typedef struct
{
    vec3_t		bounds[2];		// for culling
    msurface_t	*firstSurface;
    int			numSurfaces;
}
bmodel_t;

typedef struct
{
    char		name[MAX_QPATH];		// ie: maps/tim_dm2.bsp
    char		baseName[MAX_QPATH];	// ie: tim_dm2

    int			dataSize;

    int			numShaders;
    dshader_t	*shaders;

    bmodel_t	*bmodels;

    int			numplanes;
    cplane_t	*planes;

    int			numnodes;		// includes leafs
    int			numDecisionNodes;
    mnode_t		*nodes;

    int			numsurfaces;
    msurface_t	*surfaces;

    int			nummarksurfaces;
    msurface_t	**marksurfaces;

    int			numfogs;
    fog_t		*fogs;

    vec3_t		lightGridOrigin;
    vec3_t		lightGridSize;
    vec3_t		lightGridInverseSize;
    int			lightGridBounds[3];
    byte		*lightGridData;


    int			numClusters;
    int			clusterBytes;
    const byte	*vis;			// may be passed in by CM_LoadMap to save space

    byte		*novis;			// clusterBytes of 0xff

    char		*entityString;
    char		*entityParsePoint;
}
world_t;

//======================================================================

typedef enum {
    MOD_BAD,
    MOD_BRUSH,
    MOD_MESH,
    MOD_MD4
} modtype_t;

typedef struct model_s
{
    char		name[MAX_QPATH];
    modtype_t	type;
    int			index;				// model = tr.models[model->index]

    int			dataSize;			// just for listing purposes
    bmodel_t	*bmodel;			// only if type == MOD_BRUSH
    md3Header_t	*md3[MD3_MAX_LODS];	// only if type == MOD_MESH
    md4Header_t	*md4;				// only if type == MOD_MD4

    int			 numLods;
}
model_t;


#define	MAX_MOD_KNOWN	1024

void		R_ModelInit (void);
model_t		*R_GetModelByHandle( qhandle_t hModel );
int			R_LerpTag( orientation_t *tag, qhandle_t handle, int startFrame, int endFrame,
                 float frac, const char *tagName );
void		R_ModelBounds( qhandle_t handle, vec3_t mins, vec3_t maxs );

void		R_Modellist_f (void);

//====================================================

#define	MAX_DRAWIMAGES			2048
#define	MAX_LIGHTMAPS			256
#define	MAX_SKINS				1024


#define	MAX_DRAWSURFS			0x10000
#define	DRAWSURF_MASK			(MAX_DRAWSURFS-1)

/*
 
the drawsurf sort data is packed into a single 32 bit value so it can be
compared quickly during the qsorting process
 
the bits are allocated as follows:
 
21 - 31	: sorted shader index
11 - 20	: entity index
2 - 6	: fog index
//2		: used to be clipped flag REMOVED - 03.21.00 rad
0 - 1	: dlightmap index
 
	TTimo - 1.32
17-31 : sorted shader index
7-16  : entity index
2-6   : fog index
0-1   : dlightmap index
*/
#define	QSORT_SHADERNUM_SHIFT	17
#define	QSORT_ENTITYNUM_SHIFT	7
#define	QSORT_FOGNUM_SHIFT		2

extern	int			gl_filter_min, gl_filter_max;

/*
** performanceCounters_t
*/
typedef struct
{
    int		c_sphere_cull_patch_in, c_sphere_cull_patch_clip, c_sphere_cull_patch_out;
    int		c_box_cull_patch_in, c_box_cull_patch_clip, c_box_cull_patch_out;
    int		c_sphere_cull_md3_in, c_sphere_cull_md3_clip, c_sphere_cull_md3_out;
    int		c_box_cull_md3_in, c_box_cull_md3_clip, c_box_cull_md3_out;

    int		c_leafs;
    int		c_dlightSurfaces;
    int		c_dlightSurfacesCulled;
}
frontEndCounters_t;

#define	FOG_TABLE_SIZE		256
#define FUNCTABLE_SIZE		1024
#define FUNCTABLE_SIZE2		10
#define FUNCTABLE_MASK		(FUNCTABLE_SIZE-1)


// the renderer front end should never modify glstate_t
typedef struct
{
    int			currenttextures[32];
    int			currenttmu;
    qboolean	finishCalled;
    int			texEnv[2];
    int			faceCulling;
    unsigned long	glStateBits;
}
glstate_t;


typedef struct
{
    int		c_surfaces, c_shaders, c_vertexes, c_indexes, c_totalIndexes;
    float	c_overDraw;

    int		c_dlightVertexes;
    int		c_dlightIndexes;

    int		c_flareAdds;
    int		c_flareTests;
    int		c_flareRenders;

    int		msec;			// total msec for backend run
}
backEndCounters_t;

// all state modified by the back end is seperated
// from the front end state
typedef struct
{
    int			smpFrame;
    trRefdef_t	refdef;
    viewParms_t	viewParms;
    orientationr_t	ori;
    backEndCounters_t	pc;
    qboolean	isHyperspace;
    trRefEntity_t	*currentEntity;
    qboolean	skyRenderedThisView;	// flag for drawing sun

    qboolean	projection2D;	// if qtrue, drawstretchpic doesn't need to change modes
    float		color2D[4];
    qboolean	vertexes2D;		// shader needs to be finished
    trRefEntity_t	entity2D;	// currentEntity will point at this when doing 2D rendering
}
backEndState_t;

/*
** trGlobals_t 
**
** Most renderer globals are defined here.
** backend functions should never modify any of these fields,
** but may read fields that aren't dynamically modified
** by the frontend.
*/
typedef struct
{
    qboolean				registered;		// cleared at shutdown, set at beginRegistration

    int						visCount;		// incremented every time a new vis cluster is entered
    int						frameCount;		// incremented every frame
    int						sceneCount;		// incremented every scene
    int						viewCount;		// incremented every view (twice a scene if portaled)
    // and every R_MarkFragments call

    int						smpFrame;		// toggles from 0 to 1 every endFrame

    int						frameSceneNum;	// zeroed at RE_BeginFrame

    qboolean				worldMapLoaded;
    world_t					*world;

    const byte				*externalVisData;	// from RE_SetWorldVisData, shared with CM_Load

    image_t					*defaultImage;
    image_t					*scratchImage[32];
    image_t					*fogImage;
    image_t					*dlightImage;	// inverse-quare highlight for projective adding
    image_t					*flareImage;
    image_t					*whiteImage;			// full of 0xff
    image_t					*identityLightImage;	// full of tr.identityLightByte

    shader_t				*defaultShader;
    shader_t				*shadowShader;
    shader_t				*projectionShadowShader;

    shader_t				*flareShader;
    shader_t				*sunShader;

    int						numLightmaps;
    image_t					*lightmaps[MAX_LIGHTMAPS];

    trRefEntity_t			*currentEntity;
    trRefEntity_t			worldEntity;		// point currentEntity at this when rendering world
    int						currentEntityNum;
    int						shiftedEntityNum;	// currentEntityNum << QSORT_ENTITYNUM_SHIFT
    model_t					*currentModel;

    viewParms_t				viewParms;

    float					identityLight;		// 1.0 / ( 1 << overbrightBits )
    int						overbrightBits;		// r_overbrightBits->integer, but set to 0 if no hw gamma

    orientationr_t			ori;					// for current entity

    trRefdef_t				refdef;

    int						viewCluster;

    vec3_t					sunLight;			// from the sky shader for this level
    vec3_t					sunDirection;

    frontEndCounters_t		pc;
    int						frontEndMsec;		// not in pc due to clearing issue

    //
    // put large tables at the end, so most elements will be
    // within the +/32K indexed range on risc processors
    //
    model_t					*models[MAX_MOD_KNOWN];
    int						numModels;

    int						numImages;
    image_t					*images[MAX_DRAWIMAGES];

    // shader indexes from other modules will be looked up in tr.shaders[]
    // shader indexes from drawsurfs will be looked up in sortedShaders[]
    // lower indexed sortedShaders must be rendered first (opaque surfaces before translucent)
    int						numShaders;
    shader_t				*shaders[MAX_SHADERS];
    shader_t				*sortedShaders[MAX_SHADERS];

    int						numSkins;
    skin_t					*skins[MAX_SKINS];

    float					sinTable[FUNCTABLE_SIZE];
    float					squareTable[FUNCTABLE_SIZE];
    float					triangleTable[FUNCTABLE_SIZE];
    float					sawToothTable[FUNCTABLE_SIZE];
    float					inverseSawToothTable[FUNCTABLE_SIZE];
    float					fogTable[FOG_TABLE_SIZE];
}
trGlobals_t;

extern backEndState_t	backEnd;
extern trGlobals_t	tr;
extern glconfig_t	glConfig;		// outside of TR since it shouldn't be cleared during ref re-init
extern glstate_t	glState;		// outside of TR since it shouldn't be cleared during ref re-init


//
// cvars
//
extern cvar_t	*r_flareSize;
extern cvar_t	*r_flareFade;

extern cvar_t	*r_railWidth;
extern cvar_t	*r_railCoreWidth;
extern cvar_t	*r_railSegmentLength;

extern cvar_t	*r_ignore;				// used for debugging anything
extern cvar_t	*r_verbose;				// used for verbose debug spew
extern cvar_t	*r_ignoreFastPath;		// allows us to ignore our Tess fast paths

extern cvar_t	*r_znear;				// near Z clip plane

extern cvar_t	*r_stencilbits;			// number of desired stencil bits
extern cvar_t	*r_depthbits;			// number of desired depth bits
extern cvar_t	*r_colorbits;			// number of desired color bits, only relevant for fullscreen
extern cvar_t	*r_stereo;				// desired pixelformat stereo flag
extern cvar_t	*r_texturebits;			// number of desired texture bits
// 0 = use framebuffer depth
// 16 = use 16-bit textures
// 32 = use 32-bit textures
// all else = error

extern cvar_t	*r_measureOverdraw;		// enables stencil buffer overdraw measurement

extern cvar_t	*r_lodbias;				// push/pull LOD transitions
extern cvar_t	*r_lodscale;

extern cvar_t	*r_primitives;			// "0" = based on compiled vertex array existance
// "1" = glDrawElemet tristrips
// "2" = glDrawElements triangles
// "-1" = no drawing

extern cvar_t	*r_inGameVideo;				// controls whether in game video should be draw
extern cvar_t	*r_fastsky;				// controls whether sky should be cleared or drawn
extern cvar_t	*r_drawSun;				// controls drawing of sun quad
extern cvar_t	*r_dynamiclight;		// dynamic lights enabled/disabled
extern cvar_t	*r_dlightBacks;			// dlight non-facing surfaces for continuity

extern	cvar_t	*r_norefresh;			// bypasses the ref rendering
extern	cvar_t	*r_drawentities;		// disable/enable entity rendering
extern	cvar_t	*r_drawworld;			// disable/enable world rendering
extern	cvar_t	*r_speeds;				// various levels of information display
extern  cvar_t	*r_detailTextures;		// enables/disables detail texturing stages
extern	cvar_t	*r_novis;				// disable/enable usage of PVS
extern	cvar_t	*r_nocull;
extern	cvar_t	*r_facePlaneCull;		// enables culling of planar surfaces with back side test
extern	cvar_t	*r_nocurves;
extern	cvar_t	*r_showcluster;

extern cvar_t	*r_mode;				// video mode
extern cvar_t	*r_fullscreen;
extern cvar_t	*r_gamma;
extern cvar_t	*r_displayRefresh;		// optional display refresh option
extern cvar_t	*r_ignorehwgamma;		// overrides hardware gamma capabilities

extern cvar_t	*r_allowExtensions;				// global enable/disable of OpenGL extensions
extern cvar_t	*r_ext_compressed_textures;		// these control use of specific extensions
extern cvar_t	*r_ext_gamma_control;
extern cvar_t	*r_ext_texenv_op;
extern cvar_t	*r_ext_multitexture;
extern cvar_t	*r_ext_compiled_vertex_array;
extern cvar_t	*r_ext_texture_env_add;

extern	cvar_t	*r_nobind;						// turns off binding to appropriate textures
extern	cvar_t	*r_singleShader;				// make most world faces use default shader
extern	cvar_t	*r_roundImagesDown;
extern	cvar_t	*r_colorMipLevels;				// development aid to see texture mip usage
extern	cvar_t	*r_picmip;						// controls picmip values
extern	cvar_t	*r_finish;
extern	cvar_t	*r_drawBuffer;
extern  cvar_t  *r_glDriver;
extern	cvar_t	*r_swapInterval;
extern	cvar_t	*r_textureMode;
extern	cvar_t	*r_offsetFactor;
extern	cvar_t	*r_offsetUnits;

extern	cvar_t	*r_fullbright;					// avoid lightmap pass
extern	cvar_t	*r_lightmap;					// render lightmaps only
extern	cvar_t	*r_vertexLight;					// vertex lighting mode for better performance
extern	cvar_t	*r_uiFullScreen;				// ui is running fullscreen

extern	cvar_t	*r_logFile;						// number of frames to emit GL logs
extern	cvar_t	*r_showtris;					// enables wireframe rendering of the world
extern	cvar_t	*r_showsky;						// forces sky in front of all surfaces
extern	cvar_t	*r_shownormals;					// draws wireframe normals
extern	cvar_t	*r_clear;						// force screen clear every frame

extern	cvar_t	*r_shadows;						// controls shadows: 0 = none, 1 = blur, 2 = stencil, 3 = black planar projection
extern	cvar_t	*r_flares;						// light flares

extern	cvar_t	*r_intensity;

extern	cvar_t	*r_lockpvs;
extern	cvar_t	*r_noportals;
extern	cvar_t	*r_portalOnly;

extern	cvar_t	*r_subdivisions;
extern	cvar_t	*r_lodCurveError;
extern	cvar_t	*r_smp;
extern	cvar_t	*r_showSmp;
extern	cvar_t	*r_skipBackEnd;

extern	cvar_t	*r_ignoreGLErrors;

extern	cvar_t	*r_overBrightBits;
extern	cvar_t	*r_mapOverBrightBits;

extern	cvar_t	*r_debugSurface;
extern	cvar_t	*r_simpleMipMaps;

extern	cvar_t	*r_showImages;
extern	cvar_t	*r_debugSort;

extern	cvar_t	*r_printShaders;
extern	cvar_t	*r_saveFontData;

extern	cvar_t	*r_blur_exposure;
extern	cvar_t	*r_blur_range;
extern	cvar_t	*r_blur_strength;
extern	cvar_t	*r_blur_enabled;
extern	cvar_t	*r_floatFramebuffer;
extern	cvar_t	*r_fog_dualpass;
extern	cvar_t	*r_glsl_convert;
extern	cvar_t	*r_glsl_render;
extern	cvar_t	*r_showNonGlsl;

//====================================================================

float R_NoiseGet4f( float x, float y, float z, float t );
void  R_NoiseInit( void );

void R_SwapBuffers( int );

void R_RenderView( viewParms_t *parms );

void R_AddMD3Surfaces( trRefEntity_t *e );
void R_AddNullModelSurfaces( trRefEntity_t *e );
void R_AddBeamSurfaces( trRefEntity_t *e );
void R_AddRailSurfaces( trRefEntity_t *e, qboolean isUnderwater );
void R_AddLightningBoltSurfaces( trRefEntity_t *e );

void R_AddPolygonSurfaces( void );

void R_DecomposeSort( unsigned sort, int *entityNum, shader_t **shader,
                      int *fogNum, int *dlightMap );

void R_AddDrawSurf( surfaceType_t *surface, shader_t *shader, int fogIndex, int dlightMap );


#define	CULL_IN		0		// completely unclipped
#define	CULL_CLIP	1		// clipped by one or more planes
#define	CULL_OUT	2		// completely outside the clipping planes
void R_LocalNormalToWorld (vec3_t local, vec3_t world);
void R_LocalPointToWorld (vec3_t local, vec3_t world);
int R_CullLocalBox (vec3_t bounds[2]);
int R_CullPointAndRadius( vec3_t origin, float radius );
int R_CullLocalPointAndRadius( vec3_t origin, float radius );

void R_RotateForEntity( const trRefEntity_t *ent, const viewParms_t *viewParms, orientationr_t *ori );

/*
** GL wrapper/helper functions
*/
void	GL_Bind( image_t *image );
void	GL_SetDefaultState (void);
void	GL_SelectTexture( int unit );
void	GL_TextureMode( const char *string );
void	GL_CheckErrors( void );
void	GL_State( unsigned long stateVector );
void	GL_TexEnv( int env );
void	GL_Cull( int cullType );

#define GLS_SRCBLEND_ZERO						0x00000001
#define GLS_SRCBLEND_ONE						0x00000002
#define GLS_SRCBLEND_DST_COLOR					0x00000003
#define GLS_SRCBLEND_ONE_MINUS_DST_COLOR		0x00000004
#define GLS_SRCBLEND_SRC_ALPHA					0x00000005
#define GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA		0x00000006
#define GLS_SRCBLEND_DST_ALPHA					0x00000007
#define GLS_SRCBLEND_ONE_MINUS_DST_ALPHA		0x00000008
#define GLS_SRCBLEND_ALPHA_SATURATE				0x00000009
#define	GLS_SRCBLEND_BITS						0x0000000f

#define GLS_DSTBLEND_ZERO						0x00000010
#define GLS_DSTBLEND_ONE						0x00000020
#define GLS_DSTBLEND_SRC_COLOR					0x00000030
#define GLS_DSTBLEND_ONE_MINUS_SRC_COLOR		0x00000040
#define GLS_DSTBLEND_SRC_ALPHA					0x00000050
#define GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA		0x00000060
#define GLS_DSTBLEND_DST_ALPHA					0x00000070
#define GLS_DSTBLEND_ONE_MINUS_DST_ALPHA		0x00000080
#define	GLS_DSTBLEND_BITS						0x000000f0

#define GLS_ASRCBLEND_ZERO						0x00000100
#define GLS_ASRCBLEND_ONE						0x00000200
#define GLS_ASRCBLEND_DST_COLOR					0x00000300
#define GLS_ASRCBLEND_ONE_MINUS_DST_COLOR		0x00000400
#define GLS_ASRCBLEND_SRC_ALPHA					0x00000500
#define GLS_ASRCBLEND_ONE_MINUS_SRC_ALPHA		0x00000600
#define GLS_ASRCBLEND_DST_ALPHA					0x00000700
#define GLS_ASRCBLEND_ONE_MINUS_DST_ALPHA		0x00000800
#define GLS_ASRCBLEND_ALPHA_SATURATE			0x00000900
#define	GLS_ASRCBLEND_BITS						0x00000f00

#define GLS_ADSTBLEND_ZERO						0x00001000
#define GLS_ADSTBLEND_ONE						0x00002000
#define GLS_ADSTBLEND_SRC_COLOR					0x00003000
#define GLS_ADSTBLEND_ONE_MINUS_SRC_COLOR		0x00004000
#define GLS_ADSTBLEND_SRC_ALPHA					0x00005000
#define GLS_ADSTBLEND_ONE_MINUS_SRC_ALPHA		0x00006000
#define GLS_ADSTBLEND_DST_ALPHA					0x00007000
#define GLS_ADSTBLEND_ONE_MINUS_DST_ALPHA		0x00008000
#define	GLS_ADSTBLEND_BITS						0x0000f000

#define GLS_DEPTHMASK_TRUE						0x00010000
#define GLS_POLYMODE_LINE						0x00020000
#define GLS_DEPTHTEST_DISABLE					0x00040000
#define GLS_DEPTHFUNC_EQUAL						0x00080000

#define GLS_ATEST_GT_0							0x10000000
#define GLS_ATEST_LT_80							0x20000000
#define GLS_ATEST_GE_80							0x40000000
#define	GLS_ATEST_BITS							0x70000000

#define GLS_DEFAULT								GLS_DEPTHMASK_TRUE

void	RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty);
void	RE_UploadCinematic (int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty);

void		RE_BeginFrame( stereoFrame_t stereoFrame );
void		RE_BeginRegistration( glconfig_t *glconfig );
void		RE_LoadWorldMap( const char *mapname );
void		RE_SetWorldVisData( const byte *vis );
qhandle_t	RE_RegisterModel( const char *name );
qhandle_t	RE_RegisterSkin( const char *name );
void		RE_Shutdown( qboolean destroyWindow );

qboolean	R_GetEntityToken( char *buffer, int size );

model_t		*R_AllocModel( void );

void    	R_Init( void );
image_t		*R_FindImageFile( const char *name, qboolean mipmap, qboolean allowPicmip, int glWrapClampMode );
image_t         *R_FindTexgenImage(const char *name, const char *slot, qboolean mipmap, qboolean allowPicmip, int glWrapClampMode);

image_t		*R_CreateImage( const char *name, const byte *pic, int width, int height, qboolean mipmap
                         , qboolean allowPicmip, int wrapClampMode );
qboolean	R_GetModeInfo( int *width, int *height, float *windowAspect, int mode );

void		R_SetColorMappings( void );
void		R_GammaCorrect( byte *buffer, int bufSize );

void	R_ImageList_f( void );
void	R_SkinList_f( void );
// https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=516
const void *RB_TakeScreenshotCmd( const void *data );
void	R_ScreenShot_f( void );

void	R_InitFogTable( void );
float	R_FogFactor( float s, float t );
void	R_InitImages( void );
void	R_DeleteTextures( void );
int		R_SumOfUsedImages( void );
void	R_InitSkins( void );
skin_t	*R_GetSkinByHandle( qhandle_t hSkin );


//
// tr_shader.c
//
qhandle_t		 RE_RegisterShaderLightMap( const char *name, int lightmapIndex );
qhandle_t		 RE_RegisterShader( const char *name );
qhandle_t		 RE_RegisterShaderNoMip( const char *name );
qhandle_t RE_RegisterShaderFromImage(const char *name, int lightmapIndex, image_t *image, qboolean mipRawImage);

shader_t	*R_FindShader( const char *name, int lightmapIndex, qboolean mipRawImage );
shader_t	*R_GetShaderByHandle( qhandle_t hShader );
shader_t	*R_GetShaderByState( int index, long *cycleTime );
shader_t *R_FindShaderByName( const char *name );
void		R_InitShaders( void );
void		R_ShaderList_f( void );
void    R_RemapShader(const char *oldShader, const char *newShader, const char *timeOffset);

/*
====================================================================
 
IMPLEMENTATION SPECIFIC FUNCTIONS
 
====================================================================
*/

void		GLimp_Init( void );
void		GLimp_Shutdown( void );
void		GLimp_EndFrame( void );

qboolean	GLimp_SpawnRenderThread( void (*function)( void ) );
void		*GLimp_RendererSleep( void );
void		GLimp_FrontEndSleep( void );
void		GLimp_WakeRenderer( void *data );

void		GLimp_LogComment( char *comment );

// NOTE TTimo linux works with float gamma value, not the gamma table
//   the params won't be used, getting the r_gamma cvar directly
void		GLimp_SetGamma( unsigned char red[256],
                      unsigned char green[256],
                      unsigned char blue[256] );


/*
====================================================================
 
TESSELATOR/SHADER DECLARATIONS
 
====================================================================
*/

typedef struct stageVars
{
    vec4_t		colors[SHADER_MAX_VERTEXES];
    vec2_t		texcoords[NUM_TEXTURE_BUNDLES][SHADER_MAX_VERTEXES];
}
stageVars_t;

typedef struct shaderCommands_s
{
    glIndex_t	indexes[SHADER_MAX_INDEXES];
    vec4_t		xyz[SHADER_MAX_VERTEXES];
    vec4_t		normal[SHADER_MAX_VERTEXES];
    vec2_t		texCoords[SHADER_MAX_VERTEXES][2];
    vec4_t		vertexColors[SHADER_MAX_VERTEXES];
    int			vertexDlightBits[SHADER_MAX_VERTEXES];

    stageVars_t	svars;

    vec4_t		constantColorFull[SHADER_MAX_VERTEXES];

    shader_t	*shader;
    float		shaderTime;
    int			fogNum;

    int			dlightBits;	// or together of all vertexDlightBits

    int			numIndexes;
    int			numVertexes;

    // info extracted from current shader
    int			numPasses;
    void		(*currentStageIteratorFunc)( void );
	glShader_t	*glShader;
    shaderStage_t	**xstages;
}
shaderCommands_t;

extern	shaderCommands_t	tess;

void RB_BeginSurface(shader_t *shader, int fogNum );
void RB_EndSurface(void);
void RB_CheckOverflow( int verts, int indexes );
#define RB_CHECKOVERFLOW(v,i) if (tess.numVertexes + (v) >= SHADER_MAX_VERTEXES || tess.numIndexes + (i) >= SHADER_MAX_INDEXES ) {RB_CheckOverflow(v,i);}

void RB_StageIteratorGeneric( void );
void RB_StageIteratorSky( void );
void RB_StageIteratorOpenGLShader( void );
void RB_StageIteratorVertexLitTexture( void );
void RB_StageIteratorLightmappedMultitexture( void );

void RB_AddQuadStamp( vec3_t origin, vec3_t left, vec3_t up, float *color );
void RB_AddQuadStampExt( vec3_t origin, vec3_t left, vec3_t up, float *color, float s1, float t1, float s2, float t2 );

void RB_ShowImages( void );


/*
============================================================
 
WORLD MAP
 
============================================================
*/

void R_AddBrushModelSurfaces( trRefEntity_t *e );
void R_AddWorldSurfaces( void );
qboolean R_inPVS( const vec3_t p1, const vec3_t p2 );


/*
============================================================
 
FLARES
 
============================================================
*/

void R_ClearFlares( void );

void RB_AddFlare( void *surface, int fogNum, vec3_t point, vec3_t color, vec3_t normal );
void RB_AddDlightFlares( void );
void RB_RenderFlares (void);

/*
============================================================
 
LIGHTS
 
============================================================
*/

void R_DlightBmodel( bmodel_t *bmodel );
void R_SetupEntityLighting( const trRefdef_t *refdef, trRefEntity_t *ent );
void R_TransformDlights( int count, dlight_t *dl, orientationr_t *ori );
int R_LightForPoint( vec3_t point, vec3_t ambientLight, vec3_t directedLight, vec3_t lightDir );


/*
============================================================
 
SHADOWS
 
============================================================
*/

void RB_ShadowTessEnd( void );
void RB_ShadowFinish( void );
void RB_ProjectionShadowDeform( void );

/*
============================================================
 
SKIES
 
============================================================
*/

void R_BuildCloudData( shaderCommands_t *shader );
void R_InitSkyTexCoords( float cloudLayerHeight );
void R_DrawSkyBox( shaderCommands_t *shader );
void RB_DrawSun( void );
void RB_ClipSkyPolygons( shaderCommands_t *shader );

/*
============================================================
 
CURVE TESSELATION
 
============================================================
*/

#define PATCH_STITCHING

srfGridMesh_t *R_SubdividePatchToGrid( int width, int height,
                                       drawVertex_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE] );
srfGridMesh_t *R_GridInsertColumn( srfGridMesh_t *grid, int column, int row, vec3_t point, float loderror );
srfGridMesh_t *R_GridInsertRow( srfGridMesh_t *grid, int row, int column, vec3_t point, float loderror );
void R_FreeSurfaceGridMesh( srfGridMesh_t *grid );

/*
============================================================
 
MARKERS, POLYGON PROJECTION ON WORLD POLYGONS
 
============================================================
*/

int R_MarkFragments( int numPoints, const vec3_t *points, const vec3_t projection,
                     int maxPoints, vec3_t pointBuffer, int maxFragments, markFragment_t *fragmentBuffer );


/*
============================================================
 
SCENE GENERATION
 
============================================================
*/

void R_ToggleSmpFrame( void );

void RE_ClearScene( void );
void RE_AddRefEntityToScene( const refEntity_t *ent );
void RE_AddPolyToScene( qhandle_t hShader , int numVerts, const polyVert_t *verts, int num );
void RE_AddLightToScene( const vec3_t org, float intensity, float r, float g, float b );
void RE_AddAdditiveLightToScene( const vec3_t org, float intensity, float r, float g, float b );
void RE_RenderScene( const refdef_t *fd );

/*
=============================================================
 
ANIMATED MODELS
 
=============================================================
*/

void R_MakeAnimModel( model_t *model );
void R_AddAnimSurfaces( trRefEntity_t *ent );
void RB_SurfaceAnim( md4Surface_t *surfType );

/*
=============================================================
=============================================================
*/
void	R_TransformModelToClip( const vec3_t src, const float *modelMatrix, const float *projectionMatrix,
                             vec4_t eye, vec4_t dst );
void	R_TransformClipToWindow( const vec4_t clip, const viewParms_t *view, vec4_t normalized, vec4_t window );

void	RB_DeformTessGeometry( void );

void	RB_CalcEnvironmentTexCoords( float *dstTexCoords );
void	RB_CalcFogTexCoords( float *dstTexCoords, fog_t *fog );
void	RB_CalcScrollTexCoords( const float scroll[2], float *dstTexCoords );
void	RB_CalcRotateTexCoords( float rotSpeed, float *dstTexCoords );
void	RB_CalcScaleTexCoords( const float scale[2], float *dstTexCoords );
void	RB_CalcTurbulentTexCoords( const waveForm_t *wf, float *dstTexCoords );
void	RB_CalcTransformTexCoords( const texModInfo_t *tmi, float *dstTexCoords );
void	RB_CalcModulateColorsByFog( float *dstColors );
void	RB_CalcModulateAlphasByFog( float *dstColors );
void	RB_CalcModulateRGBAsByFog( float *dstColors );
void	RB_CalcWaveAlpha( const waveForm_t *wf, float *dstColors );
void	RB_CalcWaveColor( const waveForm_t *wf, float *dstColors );
void	RB_CalcAlphaFromEntity( float *dstColors );
void	RB_CalcAlphaFromOneMinusEntity( float *dstColors );
void	RB_CalcStretchTexCoords( const waveForm_t *wf, float *texCoords );
void	RB_CalcColorFromEntity( float *dstColors );
void	RB_CalcColorFromOneMinusEntity( float *dstColors );
void	RB_CalcSpecularAlpha( float *alphas );
void	RB_CalcDiffuseColor( float *colors );

/*
=============================================================
 
RENDERER BACK END FUNCTIONS
 
=============================================================
*/

void RB_RenderThread( void );
void RB_ExecuteRenderCommands( const void *data );

/*
=============================================================
 
RENDERER BACK END COMMAND QUEUE
 
=============================================================
*/

#define	MAX_RENDER_COMMANDS	0x40000

typedef struct
{
    byte	cmds[MAX_RENDER_COMMANDS];
    int		used;
}
renderCommandList_t;

typedef struct
{
    int		commandId;
    float	color[4];
}
setColorCommand_t;

typedef struct
{
    int		commandId;
    int		buffer;
}
drawBufferCommand_t;

typedef struct
{
    int		commandId;
    image_t	*image;
    int		width;
    int		height;
    void	*data;
}
subImageCommand_t;

typedef struct
{
    int		commandId;
}
swapBuffersCommand_t;

typedef struct
{
    int		commandId;
    int		buffer;
}
endFrameCommand_t;

typedef struct
{
    int		commandId;
    shader_t	*shader;
    float	x, y;
    float	w, h;
    float	s1, t1;
    float	s2, t2;
}
stretchPicCommand_t;

typedef struct
{
    int		commandId;
    trRefdef_t	refdef;
    viewParms_t	viewParms;
    drawSurf_t *drawSurfs;
    int		numDrawSurfs;
}
drawSurfsCommand_t;

typedef struct
{
    int commandId;
    int x;
    int y;
    int width;
    int height;
    char *fileName;
    qboolean jpeg;
}
screenshotCommand_t;

typedef enum {
    RC_END_OF_LIST,
    RC_SET_COLOR,
    RC_STRETCH_PIC,
    RC_DRAW_SURFS,
    RC_DRAW_BUFFER,
    RC_SWAP_BUFFERS,
    RC_SCREENSHOT
} renderCommand_t;


// these are sort of arbitrary limits.
// the limits apply to the sum of all scenes in a frame --
// the main view, all the 3D icons, etc
#define	MAX_POLYS		600
#define	MAX_POLYVERTS	3000

// all of the information needed by the back end must be
// contained in a backEndData_t.  This entire structure is
// duplicated so the front and back end can run in parallel
// on an SMP machine
typedef struct
{
    drawSurf_t	drawSurfs[MAX_DRAWSURFS];
    dlight_t	dlights[MAX_DLIGHTS];
    trRefEntity_t	entities[MAX_ENTITIES];
    srfPoly_t	*polys;//[MAX_POLYS];
    polyVert_t	*polyVerts;//[MAX_POLYVERTS];
    renderCommandList_t	commands;
}
backEndData_t;

extern	int		max_polys;
extern	int		max_polyverts;

extern	backEndData_t	*backEndData[SMP_FRAMES];	// the second one may not be allocated

extern	volatile renderCommandList_t	*renderCommandList;

extern	volatile qboolean	renderThreadActive;


void *R_GetCommandBuffer( int bytes );
void RB_ExecuteRenderCommands( const void *data );

void R_InitCommandBuffers( void );
void R_ShutdownCommandBuffers( void );

void R_SyncRenderThread( void );

void R_AddDrawSurfCmd( drawSurf_t *drawSurfs, int numDrawSurfs );

void RE_SetColor( const float *rgba );
void RE_StretchPic ( float x, float y, float w, float h,
                     float s1, float t1, float s2, float t2, qhandle_t hShader );
void RE_BeginFrame( stereoFrame_t stereoFrame );
void RE_EndFrame( int *frontEndMsec, int *backEndMsec );
void SaveJPG(char * filename, int quality, int image_width, int image_height, unsigned char *image_buffer);

// font stuff
void R_InitFreeType(void);
void R_DoneFreeType(void);
void RE_RegisterFont(const char *fontName, int pointSize, fontInfo_t *font);

// pbuffers
typedef struct
{
    int numColor;
    image_t *color[16];
    image_t *depth;
    image_t *stencil;
}
fboSet_t;

#define F_CLAMP_S	0x00000001
#define F_CLAMP_T	0x00000002
#define F_CLAMP_R	0x00000004
#define F_CLAMP	(F_CLAMP_S | F_CLAMP_T | F_CLAMP_R)

typedef enum
{
    F_NEAREST = 0,
    F_LINEAR = 1,
    F_NEAREST_MIPMAP_NEAREST = 2,
    F_LINEAR_MIPMAP_NEAREST = 3,
    F_NEAREST_MIPMAP_LINEAR = 4,
    F_LINEAR_MIPMAP_LINEAR = 5,
    F_NUM_FILTER = 6
} filter_e;

extern GLenum filterMin[];
extern GLenum filterMax[];

void Fbo_Bind(void);
qboolean Fbo_Unbind(void);
qboolean Fbo_IsUsable(void);
image_t *Fbo_genDepthRenderBuffer(int width, int height, int bits);
image_t *Fbo_genStencilRenderBuffer(int width, int height, int bits);
image_t *Fbo_genRenderTarget(int width, int height, int bits, filter_e filter, int flags);
void Fbo_setBuffers(GLuint numberTargets, image_t *targets[], image_t *depth, image_t *stencil);
void Fbo_getSet(fboSet_t *set);
void Fbo_applySet(fboSet_t *set);

void Shader_Compile(glShader_t *shader);
void Shader_Free(glShader_t *shader);
void Shader_Use(glShader_t *shader);
void Shader_setImage(const char *name, image_t *image);
void Shader_setConstant1i(const char *name, int constant);
void Shader_setConstant1f(const char *name, float c1);
void Shader_setConstant2f(const char *name, float c1, float c2);
void Shader_setConstant3f(const char *name, float c1, float c2, float c3);
void Shader_setConstant4f(const char *name, float c1, float c2, float c3, float c4);
void Shader_setConstant3x3f(const char *name, const float *constant);
void Shader_setConstant4x4f(const char *name, const float *constant);
void Shader_setConstantArray1f(const char *name, const float *constant, unsigned int count);
void Shader_setConstantArray2f(const char *name, const float *constant, unsigned int count);
void Shader_setConstantArray3f(const char *name, const float *constant, unsigned int count);
void Shader_setConstantArray4f(const char *name, const float *constant, unsigned int count);
void Shader_Convert(shader_t *pShader);

typedef struct
{
#if defined( _WIN32 )
    WNDPROC		wndproc;

    HDC     hDC;			// handle to device context
    HGLRC   hGLRC;			// handle to GL rendering context

    qboolean allowdisplaydepthchange;
    qboolean pixelFormatSet;
    qboolean pixelFormatARB;

    int		 desktopBitsPixel;
    int		 desktopWidth, desktopHeight;

    qboolean	cdsFullscreen;
#endif

    DYNLIBTYPE openglLibrary;

    FILE *log_fp;
}
glwstate_t;

extern glwstate_t glw_state;

#endif //TR_LOCAL_H
